/*
 * Copyright (c) 2010, University of Innsbruck, Austria.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package at.sti2.sepn.pattern.network.beta;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import at.sti2.sepn.pattern.network.WorkingMemoryElement;
import at.sti2.sepn.pattern.network.alpha.AlphaMemory;
import at.sti2.sepn.pattern.network.node.RETENode;
import at.sti2.sepn.pattern.network.node.Token;

public class JoinNode extends RETENode {

	private AlphaMemory alphaMemory = null;
	private List <JoinNodeTest> tests = null;
	
	public JoinNode(){
		tests = new ArrayList <JoinNodeTest> ();
	}
	
	public AlphaMemory getAlphaMemory() {
		return alphaMemory;
	}

	public void setAlphaMemory(AlphaMemory alphaMemory) {
		this.alphaMemory = alphaMemory;
	}

	public List<JoinNodeTest> getTests() {
		return tests;
	}
	
	public void addJoinNodeTest(JoinNodeTest test){
		tests.add(test);
	}

	@Override
	public void rightActivate(WorkingMemoryElement wme) {
		//Look into the beta memory to find any token for which tests succeed.
		for (Token betaMemoryToken : ((BetaMemory)parent).getItems())
			if (performTests(betaMemoryToken, wme))
				for (RETENode reteNode : children)
					if (reteNode instanceof BetaMemory)
						((BetaMemory)reteNode).leftActivate(betaMemoryToken, wme);
					else if (reteNode instanceof ProductionNode)
						((ProductionNode)reteNode).leftActivate(betaMemoryToken, wme);
					else
						((NegativeNode)reteNode).leftActivate(betaMemoryToken, wme);
		
		if (((BetaMemory)parent).isRootNode())
			for (RETENode reteNode : children)
				if (reteNode instanceof BetaMemory)
					((BetaMemory)reteNode).leftActivate(null, wme);
				else if (reteNode instanceof ProductionNode)
					((ProductionNode)reteNode).leftActivate(null, wme);
				else
					((NegativeNode)reteNode).leftActivate(null, wme);
		
	}

	@Override
	public void leftActivate(Token token) {
		for (WorkingMemoryElement alphaWME : alphaMemory.getItems())
			if (performTests(token, alphaWME))
				for (RETENode reteNode : children)
					if (reteNode instanceof BetaMemory)
						((BetaMemory)reteNode).leftActivate(token, alphaWME);
					else if (reteNode instanceof ProductionNode)
						((ProductionNode)reteNode).leftActivate(token, alphaWME);
					else
						((NegativeNode)reteNode).leftActivate(token, alphaWME);
	}
	
	public void setTests(List<JoinNodeTest> tests) {
		this.tests = tests;
	}

	public boolean performTests (Token token, WorkingMemoryElement wme){
		
		String lexicalValueArg1 = null;
		String lexicalvalueArg2 = null;
		
		for (JoinNodeTest test : tests){
			lexicalValueArg1 = wme.getTriple().getLexicalValueOfField(test.getArg1Field());
			
			//Select WME
			int index = test.getArg2ConditionNumber();
			
			//TODO Fix this for faster processing; instead of using indices maybe we can use pointers?!
			//The value I have is the one of index in the tree, while the only thing I have is the token from which to start.
			
			Vector<Token> wmeTokenVect = getTokenVect(token);
			Token wmeToken = wmeTokenVect.get(index);
			
			lexicalvalueArg2 = wmeToken.getWme().getTriple().getLexicalValueOfField(test.getArg2Field());
			
			if (!lexicalValueArg1.equals(lexicalvalueArg2))
				return false;
		}
		
		return true;
	}
	
	private Vector<Token> getTokenVect(Token token){
		
		Vector <Token> tokenVect = new Vector <Token>();
		
		Token tempToken = token;
		
		while (tempToken != null){
			tokenVect.add(0, tempToken);
			tempToken = tempToken.getParent();
		}
			
		return tokenVect;
		
	}

	@Override
	public void leftActivate(Token token, WorkingMemoryElement wme) {
		// TODO Auto-generated method stub
	}
}
